from fastapi.security import OAuth2PasswordRequestForm
from fastapi import APIRouter, Depends, Request, HTTPException, status
from typing import Optional
from sqlalchemy.future import select
from sqlmodel.ext.asyncio.session import AsyncSession
from schemas.common import RETURN
from schemas.user import LoginParams, RegisterParams, LoginResponse

from core.Depend import check_api_token, has_api_permission
from database.mysql import get_async_session
from utils.jwtToken import verify_password, generate_token, get_password_hash

import models.Base as BaseModel
import models.admin.user.user as UserModel
import models.admin.user.third_user as ThirdUserModel

import json
import time

from core.Config import settings


router = APIRouter(prefix="/user", tags=["api-用户管理"])
dataLimit = False

# 缓存用户信息
async def cache_game_user(user: UserModel.Game_User, request: Request, session: AsyncSession):
    # 缓存当前用户信息
    third_user = {}
    if user.type == UserModel.UserType.THIRD_PARTY:
        state = select(ThirdUserModel.Game_Third_User).where(ThirdUserModel.Game_Third_User.user_id == user.id)
        result = await session.exec(state)
        third_user = result.scalars().first()

    redis_user = UserModel.redis_user(
        id=user.id,
        nickname=user.nickname,
        username=user.username,
        group_id=user.group_id,
        gender=user.gender,
        bio=user.bio,
        money=user.money,
        score=user.score,
        level=user.level,
        mobile=user.mobile,
        third_user=third_user.model_dump() if hasattr(third_user, 'model_dump') else third_user
    )

    # 查询权限，进行缓存
    statement = select(UserModel.Game_Group_Rule_Link.rule_id).where(UserModel.Game_Group_Rule_Link.group_id == user.group_id)
    result = await session.exec(statement)
    rules = result.scalars().all()

    statement = select(UserModel.Game_User_Rule.auths).where(UserModel.Game_User_Rule.id.in_(rules)).where(UserModel.Game_User_Rule.menu_type == UserModel.MenuTypeEnum.BUTTON)
    result = await session.exec(statement)
    user_rules = result.scalars().all()
    
    await request.app.state.cache.set(f"gameuser:{user.username}_auths", json.dumps(user_rules))
    await request.app.state.cache.set(f"gameuser:{user.username}", json.dumps(redis_user.model_dump()))
    return user


@router.post("/getAccessToken",summary="获取token",response_model=BaseModel.Token)
async def login_for_access_token(
    form_data: OAuth2PasswordRequestForm = Depends(),
    session: AsyncSession = Depends(get_async_session)
) -> BaseModel.Token:
    statement = select(UserModel.Game_User).where(UserModel.Game_User.username == form_data.username)
    result = await session.exec(statement)
    admin_user:UserModel.Game_User = result.scalars().first()
    if admin_user is None or  admin_user.status == BaseModel.StatusTypeEnum.ABNORMAL:
        raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="Incorrect username or password",
                headers={"WWW-Authenticate": "Bearer"},
            )
    token = generate_token(form_data.username,settings.SESSION_MAX_AGE)
    return BaseModel.Token(access_token=token['accessToken'], token_type="bearer")


# 账号密码登录
@router.post("/login", response_model=RETURN[Optional[LoginResponse]])
async def login(login: LoginParams, request: Request, session: AsyncSession = Depends(get_async_session)):
    user = await session.exec(select(UserModel.Game_User).filter(UserModel.Game_User.username == login.username))
    user = user.scalars().first()
    if not user:
        return RETURN.fail("用户名不存在")
    if not verify_password(login.password, user.password):
        return RETURN.fail("密码错误")
    token = generate_token(user.username, settings.SESSION_MAX_AGE)
    # 进行登录缓存
    # 缓存当前用户信息
    # 通过角色id缓存用户权限
    await cache_game_user(user, request, session)

    result = LoginResponse(
        id=user.id,
        nickname=user.nickname,
        group_id=user.group_id,
        gender=user.gender,
        bio=user.bio,
        money=user.money,
        score=user.score,
        level=user.level,
        mobile=user.mobile,
        accessToken=token["accessToken"],
        refreshToken=token["refreshToken"],
        expires=token["expires"]
      )
    return RETURN.success("登录成功", result)

# 注册
@router.post("/register", response_model=RETURN)
async def register(user: RegisterParams, request: Request, session: AsyncSession = Depends(get_async_session)):
    state = select(UserModel.Game_User).where(UserModel.Game_User.username == user.username)
    result = await session.exec(state)
    obj = result.scalars().first()
    if obj:
        return RETURN.fail("用户名已存在")
    
    state = select(UserModel.Game_User).where(UserModel.Game_User.mobile == user.mobile)
    result = await session.exec(state)
    obj = result.scalars().first()
    if obj:
        return RETURN.fail("手机号已存在")
    
    state = select(UserModel.Game_User).where(UserModel.Game_User.email == user.email)
    result = await session.exec(state)
    obj = result.scalars().first()
    if obj:
        return RETURN.fail("邮箱已存在")
    
    user.joinip =  request.client.host
    user.jointime = time.time() 
    user.password = get_password_hash(user.password)
    add_user = UserModel.Game_User(**user.model_dump())
    add_user.type = UserModel.UserType.DEFAULT
    session.add(add_user)
    await session.commit()
    return RETURN.success("注册成功",user)
    
from addons.third.Service import ThirdServer

# 第三方登录
@router.post("/thirdLogin", response_model=RETURN)
async def third_login(platform: str, code: str, request: Request, session: AsyncSession = Depends(get_async_session)):
    userinfo = await ThirdServer.get_user_info(platform, {"code": code}, request)
    return RETURN.success("登录成功", userinfo)


# 测试token
@router.get("/testToken", response_model=RETURN)
async def test_token(user: UserModel.redis_user = Depends(check_api_token)):
    return RETURN.success("token验证成功", user)

# 验证权限
@router.get("/testPermission", response_model=RETURN)
async def test_token(user: UserModel.redis_user = Depends(has_api_permission("fdsfsfa"))):
    return RETURN.success("Permission验证成功",user)